from fastapi.exceptions import RequestValidationError
from starlette.exceptions import HTTPException
from starlette.requests import Request
from starlette.responses import JSONResponse
from fastapi import status

from app.dependencies import request_id
from app.config import appLogger

from typing import Union


# 全局异常
async def global_exception_handler(request: Request, exc) -> JSONResponse:
  appLogger.info("request http_error",
                 extra={"requestId": request_id.get(), "object": f"[{request.method}]{request.url}",
                        "query": request.query_params})
  return JSONResponse(
    status_code=exc.status_code,
    content={"msg": exc.detail},
  )


# 请求数据无效
async def validation_exception_handler(request: Request, exc: RequestValidationError) -> JSONResponse:
  return JSONResponse(
    status_code=status.HTTP_200_OK,
    content={
      "code": status.HTTP_422_UNPROCESSABLE_ENTITY,
      "msg": "入参类型错误",
      "data": {
        "error": exc.args,
        "body": exc.body,
        "pathParams": request.path_params,
        "queryParams": dict(request.query_params),
      }
    }
  )


class BaseException(HTTPException):
  def __init__(self, status_code: Union[int, str] = 400, detail: str = "未知错误"):
    self.status_code = status_code
    self.detail = detail


async def base_exception(request: Request, exc: BaseException) -> JSONResponse:
  appLogger.info("request api_error",
                 extra={"requestId": request_id.get(), "object": f"[{request.method}]{request.url}",
                        "query": request.query_params})
  return JSONResponse(
    status_code=status.HTTP_200_OK,
    content={
      "code": exc.status_code,
      "msg": exc.detail,
    }
  )


golbal_exception_handlers = {
  HTTPException: global_exception_handler,
  RequestValidationError: validation_exception_handler,
  BaseException: base_exception,
}
